Fix reload-from-disk: matching, positions, deleted bodies, STEP names#10380
Open
jomixlaf wants to merge 11 commits intobambulab:masterfrom
Open
Fix reload-from-disk: matching, positions, deleted bodies, STEP names#10380jomixlaf wants to merge 11 commits intobambulab:masterfrom
jomixlaf wants to merge 11 commits intobambulab:masterfrom
Conversation
…ansfer map OCCT's XCAF layer only preserves names from PRODUCT entities, so bodies that live directly inside a root Fusion 360 component (stored as MANIFOLD_SOLID_BREP in STEP) were always imported as "SOLID" regardless of their actual name. After the XCAF transfer, iterate all STEP entities via the transfer process to build a TShape-pointer → MANIFOLD_SOLID_BREP-name map. getNamedSolids now consults this map when naming solid shapes, so tags like [f3] embedded in a body name are correctly preserved and subsequently applied by the smart-import naming rules.
…nents
When a Fusion 360 file has a body directly inside the root component, OCCT's
XCAF layer creates a virtual label for that geometry with a shape-type default
name ("SOLID") rather than the component/product name. The previous approach
tried to recover the MANIFOLD_SOLID_BREP entity name (the body name), but that
gives the wrong result — users should tag the *component* name, not the body
name, consistent with how sub-components already work.
Fix: treat OCCT shape-type default strings (SOLID, COMPOUND, SHELL, etc.) as
missing names and fall back to the parent component name (prefix). Bodies that
live directly in an assembly component now inherit the component name so tags
like [f3] or [neg] placed on the component are correctly applied on import.
Two issues with reload from disk for STEP files: 1. New bodies added to the STEP file were never imported — the reload loop only iterated over existing volumes looking for matches, so anything new in the file was silently dropped. 2. Component name changes didn't trigger naming rule re-evaluation because the old config/type were restored after loading without re-running rules. Fix: track which new_model volumes were matched during the update loop, then add all unmatched volumes as new volumes to the target object. Naming rules are applied to both updated and newly added volumes so filament/type tags are always current with what's in the file on disk.
…odies When a STEP file is updated with new bodies, existing volumes can shift to different indices in the newly-loaded model. The previous source-index match only checked input_file, so adding a body could silently match the wrong volume and copy its type/config onto a different volume (e.g. giving the wrong part a NEGATIVE_VOLUME type). Now the candidate must also have the same name as the old volume before the source-index match is accepted.
After reloading volumes from disk, the sidebar object list was not updated, leaving stale volume names, types, and filament columns from before the reload. Now add_volumes_to_object_in_list() is called for every modified object after the reload loop completes, so the sidebar immediately reflects new component names, updated tags, and newly-added volumes.
Previously, renaming a component (e.g. polo[f2] → polo[f5]) caused reload to fail with an error because source-index+name and name-search both required the old name. Now matching uses three passes: Pass 1: source index + exact name match (unchanged bodies) Pass 2: name search (body moved to different index, name kept) Pass 3: source index only (body renamed in place) Already-claimed new_model slots are skipped at every pass to prevent two old volumes from mapping to the same new geometry. Source indices on the resulting volume are updated to the new model positions so the next reload also finds the correct slot.
Three related fixes: 1. Deleted bodies: when a body no longer exists in the reloaded STEP file (deleted from Fusion), it now gets silently removed from the model instead of showing an error and leaving a stale volume behind. 2. sort_volumes moved out of per-volume loop: calling sort_volumes after each swap/delete was reordering the volumes array and making later vol_idx values point to the wrong volumes, causing duplicates and missed updates. sort_volumes is now called once after the loop for all modified objects. 3. Deleted-volume cleanup: volumes marked as deleted are removed in reverse index order after the loop so earlier indices stay valid.
When a body is added to a Fusion 360 STEP file and the model is reloaded, the new body appeared at the center of the plate instead of its correct position. Root cause: center_around_origin() shifts all volumes by -bb_center. On initial import the bb_center is computed from the original set of bodies; on reload new_model has an extra body that shifts the bounding-box center. Matched volumes are repositioned via old_volume->get_transformation(), so they land correctly. New (unmatched) volumes were copied directly from new_model, which uses the new shifted center — wrong coordinate frame. Fix: capture coord_shift = old_offset - new_model_offset from the first matched volume. This equals new_bb_center - initial_bb_center. Apply the shift to every newly added volume so it lands in the same coordinate frame as the existing volumes.
Pass 2 (name-based fallback) was gated by has_name, which only fires when old_volume->name equals the reloaded file's filename — false for multi-body STEP files where each body has its own name. The result: Pass 2 never ran, and when Fusion reordered bodies in the new STEP, Pass 1 missed and Pass 3 fell through, matching by source.volume_idx alone and routing the wrong body's transform. Run Pass 2 whenever the volume has a name; the outer has_source || has_name gate already restricts processing to volumes from the file being reloaded.
Previously, set_transformation(old_volume->get_transformation()) preserved the matched volume's old position regardless of whether the body moved in CAD. This broke when users repositioned bodies between exports — matched bodies stayed at stale offsets while only their meshes updated. Use the new STEP position translated by coord_shift instead. For the first matched volume (which defines coord_shift), this yields its old offset exactly, keeping the object's plate anchor stable. For all other volumes, it tracks their new STEP positions in the existing scene's coordinate frame.
The previous attempt of passing a replacement char to TCollection_AsciiString did not engage as expected (OCCT's behavior with that constructor preserved raw high bytes). A lone byte like 0xE9 (é) or 0xA0 (NBSP) then failed StepPreProcessor::isUtf8 and the body fell back to the parent component name, losing both the name and any [tag] inside it. Walk the OCCT extended (UTF-16) string codepoint by codepoint and emit a benign space for anything outside printable ASCII. Pure ASCII output always passes isUtf8, so the user's tags are preserved no matter what character they paste into a body name in Fusion.
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR fixes a number of long-standing issues with the Reload from disk action when the source file is a STEP exported from CAD (Fusion 360 in particular). It also tightens up the STEP loader's body name extraction so that bodies don't lose their identity on reload.
I believe it would fix most, if not all, of these issues listed here, some I experienced myself.
https://github.com/bambulab/BambuStudio/issues/9478
https://github.com/bambulab/BambuStudio/issues/8982
https://github.com/bambulab/BambuStudio/issues/1600
All changes live behind the existing
ENABLE_RELOAD_FROM_DISK_REWORKcompile flag for the reload-path edits, plus targeted fixes in the STEP loader.STEP loader
MANIFOLD_SOLID_BREPbody names via the entity transfer map. Bodies that previously came in asBody1/Body4/etc. now carry their authored names from the STEP product hierarchy.TCollection_AsciiString(extString)preserved raw high bytes, which then failedStepPreProcessor::isUtf8(a lone0xA0/0xE9is not a valid UTF-8 start). The body would silently fall back to the parent component name. Walking the extended string codepoint-by-codepoint and emitting a benign space for anything outside printable ASCII keeps the user's name intact (e.g.cylinder<NBSP>[f4]is no longer rejected).Reload-from-disk
old_volume->name == path.filename()) was never true for multi-body STEP, so reorders fell through to Pass 3 and matched by index alone, swapping transforms between bodies.sort_volumesout of the matching loop so it doesn't corrupt subsequentvol_idxvalues.coord_shiftcaptured from the first matched volume — the difference between the initial bb-center and the new bb-center. Applied to unmatched new bodies so they land in the existing scene's coordinate frame.set_transformation(old_volume->get_transformation())with applyingcoord_shiftto the new volume's offset. For the first matched volume this yields exactly the old offset (preserving the object's plate anchor); for subsequent volumes it tracks any repositioning the user did in CAD between exports while keeping the object anchored.Test plan
é, NBSP) → name imports without falling back to the parent assembly name.